package jetpack.com.pzl;

import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.work.ArrayCreatingInputMerger;
import androidx.work.BackoffPolicy;
import androidx.work.Constraints;
import androidx.work.Data;
import androidx.work.ExistingWorkPolicy;
import androidx.work.NetworkType;
import androidx.work.OneTimeWorkRequest;
import androidx.work.OverwritingInputMerger;
import androidx.work.PeriodicWorkRequest;
import androidx.work.WorkInfo;
import androidx.work.WorkManager;
import androidx.work.WorkRequest;

import com.google.common.util.concurrent.ListenableFuture;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;

import jetpack.com.pzl.works.DownloadWorker;
import jetpack.com.pzl.works.LoadNetTextWorker;
import jetpack.com.pzl.works.TiredWorker;
import jetpack.com.pzl.works.UploadWorker;
import jetpack.com.pzl.works.Worker1;
import jetpack.com.pzl.works.Worker2;
import jetpack.com.pzl.works.Worker3;


public class WorkManagerActivity extends AppCompatActivity {
    private TextView tvMsg2;
    private EditText etInputData;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_work_manager);

        tvMsg2 = findViewById(R.id.tvJecpackMsg2);
        etInputData = findViewById(R.id.etJetpackInputData);

        tvMsg2.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                tvMsg2.setText("");
                return true;
            }
        });
    }


    public void click(View view) {
        switch (view.getId()) {
            case R.id.btnJetpackWorkManagerRunOnce:
                //WorkRequest 配置任务调度方式
                WorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class).build();
                WorkManager.getInstance(this).enqueue(uploadWorkRequest);
                break;
            case R.id.btnJetpackWorkManagerRunPeriod:
                //周期重复性任务
                //注意：可以定义的最短重复间隔是 15 分钟（与 JobScheduler API 相同）
                /**
                 * SECONDS
                 * DAYS
                 * HOURS
                 * MICROSECONDS
                 * MILL ISECONDS
                 * MINUTES
                 * NTANOSECONDS
                 */
                PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(UploadWorker.class, 15, TimeUnit.MINUTES).build();
                WorkManager.getInstance(this).enqueue(periodicWorkRequest);
                break;
            case R.id.btnJetpackWorkManagerRunPeriod2:
                //在每小时的最后 15 分钟内运行的定期工作
                /**
                 *
                 *           [     before flex     |     flex     ][     before flex     |     flex     ]...
                 *           [   cannot run work   | can run work ][   cannot run work   | can run work ]...
                 *           \____________________________________/\____________________________________/...
                 *                          interval 1                            interval 2             ...(repeat)
                 *
                 */
                PeriodicWorkRequest periodicWorkRequest2 = new PeriodicWorkRequest.Builder(UploadWorker.class, 1, TimeUnit.HOURS, 15, TimeUnit.MINUTES).build();
                WorkManager.getInstance(this).enqueue(periodicWorkRequest2);
                break;
            case R.id.btnJetpackWorkManagerRunConstraints:
                //任务运行的约束条件
                Constraints constraints = new Constraints.Builder()
                        .setRequiredNetworkType(NetworkType.CONNECTED)//网络连接了
                        .setRequiresCharging(true)//处于充电状态
                        .build();
                WorkRequest workRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
                        .setConstraints(constraints)
                        .build();
                WorkManager.getInstance(this).enqueue(workRequest);
                break;
            case R.id.btnJetpackWorkManagerRunInitialDelay:
                //在加入队列后至少经过 10 分钟后再运行(定期工作只有首次运行时会延迟)
                WorkRequest workRequest2 = new OneTimeWorkRequest.Builder(UploadWorker.class)
                        .setInitialDelay(10, TimeUnit.MINUTES)
                        .build();
                WorkManager.getInstance(this).enqueue(workRequest2);
                break;
            case R.id.btnJetpackWorkManagerBackoffPolicy:
                //任务失败时重试策略
                WorkRequest workRequest3 = new OneTimeWorkRequest.Builder(DownloadWorker.class)
                        //任务重试的退避策略
                        /**
                         * MIN_BACKOFF_MILLIS 为10s
                         * LINEAR : 对重试的延迟时间为线性增长，  20 秒、30 秒、40 秒后重试，以此类推
                         * EXPONENTIAL ： 重试时长序列将接近 20、40、80 秒，以此类推 增倍
                         */
                        .setBackoffCriteria(BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS)
                        .build();
                WorkManager.getInstance(this).enqueue(workRequest3);
                break;
            case R.id.btnJetpackWorkManagerTagWorker:
                /**
                 * 给任务添加标记
                 * 每个工作请求都有一个唯一标识符，该标识符可用于在以后标识该工作，以便取消工作或观察其进度
                 */
                WorkRequest workRequest1 = new OneTimeWorkRequest.Builder(TiredWorker.class)
                        .addTag("TiredWorker1")
                        .build();
                WorkManager.getInstance(this).enqueue(workRequest1);
                break;
            case R.id.btnJetpackWorkManagerTagGetInfo:
                ListenableFuture<List<WorkInfo>> listenableFuture = WorkManager.getInstance(this).getWorkInfosByTag("TiredWorker1");
                try {
                    List<WorkInfo> workInfos = listenableFuture.get();
                    for (WorkInfo item : workInfos) {
                        item.toString();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                break;
            case R.id.btnJetpackWorkManagerTagCancel:
                WorkManager.getInstance(this).cancelAllWorkByTag("TiredWorker1");
                break;
            case R.id.btnJetpackWorkManagerInputData:
                String url = etInputData.getText().toString().trim();
                //构建传入参数
                Data.Builder dataBuilder = new Data.Builder();
                dataBuilder.putString("url", url);
                Data data = dataBuilder.build();
                //任务调度方式配置
                WorkRequest workRequest4 = new OneTimeWorkRequest.Builder(LoadNetTextWorker.class)
                        .setInputData(data)//设置自定义参数传入worker
                        .addTag("tag_netText")//设置任务tag标记（可能存在同一个tag对应多个任务的情况）
                        .build();
                WorkManager.getInstance(this).enqueue(workRequest4);
                // WorkInfo 对象的 ListenableFuture，该值包含工作的 id、其标记、其当前的 State 以及通过 Result.success(outputData) 设置的任何输出数据
                LiveData<List<WorkInfo>> liveData = WorkManager.getInstance(this).getWorkInfosByTagLiveData("tag_netText");
                //监听观察 WorkInfo 的变化
                liveData.observe(this, new Observer<List<WorkInfo>>() {
                    @Override
                    public void onChanged(List<WorkInfo> workInfos) {
                        for (WorkInfo workInfo : workInfos) {
                            //成功的任务
                            if (workInfo.getState() != null && workInfo.getState() == WorkInfo.State.SUCCEEDED) {
                                Data data1 = workInfo.getOutputData();//取出任务结果
                                String re = data1.getString("result");
                                tvMsg2.append("任务Id = " + workInfo.getId().toString() + "\n");
                                tvMsg2.append("结果 = " + re + "\n\n");
                            }
                        }
                    }
                });
                break;
            case R.id.btnJetpackWorkManagerUniqueTagRequest:
                //一个Tag标签唯一对应一个请求任务
                OneTimeWorkRequest workRequest5 = new OneTimeWorkRequest.Builder(UploadWorker.class).build();
                //策略为保持现状，新来的同一标签任务不执行 （策略：REPLACE，KEEP，APPEND，APPEND_OR_REPLACE）
                WorkManager.getInstance(this).beginUniqueWork("tag_upload", ExistingWorkPolicy.KEEP, workRequest5)
                        .enqueue();
                break;
            case R.id.btnJetpackWorkManagerLianJieWorkOverwriting:
                //OverwritingInputMerger 如果合并过程中没有键冲突，键的最新值将覆盖生成的输出数据中的所有先前版本。
                //OverwritingInputMerger 并行的合并任务的key如果发生冲突，那么最后完成任务的结果会覆盖较早结束任务的结果
                OneTimeWorkRequest w1 = new OneTimeWorkRequest.Builder(Worker1.class)
                        .setInputMerger(OverwritingInputMerger.class)
                        .build();//outputData key = result1
                OneTimeWorkRequest w2 = new OneTimeWorkRequest.Builder(Worker2.class)
                        .setInputMerger(OverwritingInputMerger.class)
                        .build();//outputData key = result2
                OneTimeWorkRequest w3 = new OneTimeWorkRequest.Builder(Worker3.class)
                        .setInputMerger(OverwritingInputMerger.class)
                        .build();//outputData key = result2

                OneTimeWorkRequest w_uploadWork = new OneTimeWorkRequest.Builder(UploadWorker.class)
                        .build();
                OneTimeWorkRequest w_download = new OneTimeWorkRequest.Builder(DownloadWorker.class)
                        .build();

                WorkManager.getInstance(this)
                        .beginWith(Arrays.asList(w1, w2, w3))//可能并行运行
                        .then(w_uploadWork)
                        .then(w_download)
                        .enqueue();
                break;
            case R.id.btnJetpackWorkManagerLianJieWorkArrayCreating:
                //ArrayCreatingInputMerger 若存在键冲突，在合并器中保留所有输出数据
                //存在任何键冲突，那么发生冲突key对应的值会分组到一个数组中。
                OneTimeWorkRequest w01 = new OneTimeWorkRequest.Builder(Worker1.class)
                        .setInputMerger(ArrayCreatingInputMerger.class)
                        .build();//outputData key = result1
                OneTimeWorkRequest w02 = new OneTimeWorkRequest.Builder(Worker2.class)
                        .setInputMerger(ArrayCreatingInputMerger.class)
                        .build();//outputData key = result2
                OneTimeWorkRequest w03 = new OneTimeWorkRequest.Builder(Worker3.class)
                        .setInputMerger(ArrayCreatingInputMerger.class)
                        .build();//outputData key = result2

                OneTimeWorkRequest w_Upload = new OneTimeWorkRequest.Builder(UploadWorker.class)
                        .build();
                OneTimeWorkRequest w_Download = new OneTimeWorkRequest.Builder(DownloadWorker.class)
                        .build();

                WorkManager.getInstance(this)
                        .beginWith(Arrays.asList(w01, w02, w03))//可能并行运行
                        .then(w_Upload)
                        .then(w_Download)
                        .enqueue();
                break;
        }
    }


}
